#pragma once

#include "list.h"

template<typename first, typename second, size_t carry>
struct addition_reversed
{
   typedef list_t<
      (first::head_ + second::head_ + carry) % BASE,
      typename addition_reversed<
         typename first::tail_,
         typename second::tail_,
         (first::head_ + second::head_ + carry) / BASE
      >::result_
   > result_;
};

template<typename first, size_t carry>
struct addition_reversed<first, empty_list_t, carry>
{
   typedef list_t<
      (first::head_ + 0 + carry) % BASE,
      typename addition_reversed<
         typename first::tail_,
         empty_list_t,
         (first::head_ + 0 + carry) / BASE
      >::result_
   > result_;
};

template<typename second, size_t carry>
struct addition_reversed<empty_list_t, second, carry>
{
   typedef list_t<
      (0 + second::head_ + carry) % BASE,
      typename addition_reversed<
         empty_list_t,
         typename second::tail_,
         (0 + second::head_ + carry) / BASE
      >::result_
   > result_;
};

template<size_t carry>
struct addition_reversed<empty_list_t, empty_list_t, carry>
{
   typedef list_t<
      (0 + 0 + carry) % BASE,
      typename addition_reversed<
         empty_list_t,
         empty_list_t,
         (0 + 0 + carry) / BASE
      >::result_
   > result_;
};

template<>
struct addition_reversed<empty_list_t, empty_list_t, 0>
{
   typedef empty_list_t result_;
};

template<typename first, typename second>
struct addition
{
   typedef typename reverse<
      typename addition_reversed<
         typename reverse<first>::result_,
         typename reverse<second>::result_,
         0
      >::result_
   >::result_ result_;
};